package ar.com.age.distribuidora.presentacion.controller;

import java.util.Date;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import org.primefaces.model.chart.Axis;
import org.primefaces.model.chart.AxisType;
import org.primefaces.model.chart.BarChartModel;
import org.primefaces.model.chart.ChartSeries;
import org.primefaces.model.chart.LineChartModel;

import ar.com.age.distribuidora.dominio.Cliente;
import ar.com.age.distribuidora.dominio.Producto;
import ar.com.age.distribuidora.dominio.Proveedor;
import ar.com.age.distribuidora.dominio.TipoRubro;
import ar.com.age.distribuidora.presentacion.util.ServiceLocator;
import ar.com.age.distribuidora.presentacion.util.ValidadorTipoUsuario;
import ar.com.age.distribuidora.service.nodo.NodoInformes;

@ManagedBean
@ViewScoped
public class InformesBean {
	
	private String intervaloSeleccionado;
	
	private String tipoGraficoSeleccionado;
	
	private List<Producto> productos;
	
	private Producto productoSeleccionado;
	
	private List<Cliente> clientes;
	
	private Cliente clienteSeleccionado;
	
	private List<Proveedor> proveedores;
	
	private Proveedor proveedorSeleccionado;
	
	private List<TipoRubro> tiposRubro;
	
	private TipoRubro tipoRubroSeleccionado;
	
	private Date fechaDesde;

	private Date fechaHasta;
	
	private boolean visiblilidadPanelInformeBarras;
	
	private boolean visiblilidadPanelInformeLineas;
	
	// Estructuras para los graficos
	private LineChartModel graficoLineas;
	
    private BarChartModel graficoBarras;
 
    public InformesBean() {
    	
    	ValidadorTipoUsuario.validarGerente();
    	
    	this.tiposRubro = ServiceLocator.getDatosClienteService().buscarTodosTipoRubro();
    	this.clientes = ServiceLocator.getClienteService().buscarTodos();
    	this.productos = ServiceLocator.getProductoService().buscarTodos();
    	this.proveedores = ServiceLocator.getProveedorService().buscarTodos();
    	
    	this.visiblilidadPanelInformeBarras = false;
    	this.visiblilidadPanelInformeLineas = false;
    	
    	this.graficoBarras = new BarChartModel();
    	this.graficoLineas = new LineChartModel();
    	    	
    }


	public String getTipoGraficoSeleccionado() {
		return tipoGraficoSeleccionado;
	}

	public void setTipoGraficoSeleccionado(String tipoGraficoSeleccionado) {
		this.tipoGraficoSeleccionado = tipoGraficoSeleccionado;
	}

	public String getIntervaloSeleccionado() {
		return intervaloSeleccionado;
	}

	public void setIntervaloSeleccionado(String intervaloSeleccionado) {
		this.intervaloSeleccionado = intervaloSeleccionado;
	}

	public List<Proveedor> getProveedores() {
		return proveedores;
	}

	public void setProveedores(List<Proveedor> proveedores) {
		this.proveedores = proveedores;
	}

	public Proveedor getProveedorSeleccionado() {
		return proveedorSeleccionado;
	}

	public void setProveedorSeleccionado(Proveedor proveedorSeleccionado) {
		this.proveedorSeleccionado = proveedorSeleccionado;
	}

	public LineChartModel getGraficoLineas() {
		return graficoLineas;
	}

	public void setGraficoLineas(LineChartModel graficoLineas) {
		this.graficoLineas = graficoLineas;
	}

	public BarChartModel getGraficoBarras() {
		return graficoBarras;
	}

	public void setGraficoBarras(BarChartModel graficoBarras) {
		this.graficoBarras = graficoBarras;
	}

	public boolean isVisiblilidadPanelInformeBarras() {
		return visiblilidadPanelInformeBarras;
	}

	public void setVisiblilidadPanelInformeBarras(boolean visiblilidadPanelInformeBarras) {
		this.visiblilidadPanelInformeBarras = visiblilidadPanelInformeBarras;
	}

	public boolean isVisiblilidadPanelInformeLineas() {
		return visiblilidadPanelInformeLineas;
	}

	public void setVisiblilidadPanelInformeLineas(boolean visiblilidadPanelInformeLineas) {
		this.visiblilidadPanelInformeLineas = visiblilidadPanelInformeLineas;
	}

	public List<Producto> getProductos() {
		return productos;
	}

	public void setProductos(List<Producto> productos) {
		this.productos = productos;
	}

	public Producto getProductoSeleccionado() {
		return productoSeleccionado;
	}

	public void setProductoSeleccionado(Producto productoSeleccionado) {
		this.productoSeleccionado = productoSeleccionado;
	}

	public List<Cliente> getClientes() {
		return clientes;
	}

	public void setClientes(List<Cliente> clientes) {
		this.clientes = clientes;
	}

	public Cliente getClienteSeleccionado() {
		return clienteSeleccionado;
	}

	public void setClienteSeleccionado(Cliente clienteSeleccionado) {
		this.clienteSeleccionado = clienteSeleccionado;
	}

	public List<TipoRubro> getTiposRubro() {
		return tiposRubro;
	}

	public void setTiposRubro(List<TipoRubro> tiposRubro) {
		this.tiposRubro = tiposRubro;
	}

	public TipoRubro getTipoRubroSeleccionado() {
		return tipoRubroSeleccionado;
	}

	public void setTipoRubroSeleccionado(TipoRubro tipoRubroSeleccionado) {
		this.tipoRubroSeleccionado = tipoRubroSeleccionado;
	}

	public Date getFechaDesde() {
		return fechaDesde;
	}

	public void setFechaDesde(Date fechaDesde) {
		this.fechaDesde = fechaDesde;
	}

	public Date getFechaHasta() {
		return fechaHasta;
	}

	public void setFechaHasta(Date fechaHasta) {
		this.fechaHasta = fechaHasta;
	}
    
	
	// Metodos
	
	private void setearGrafico(List<NodoInformes> nodos, int tipoInforme, String titulo) {
		
		Axis yAxis = null;
		
		switch (tipoInforme) {
			
		case 1: // Grarico de Barras
	        
			this.visiblilidadPanelInformeBarras = true;
			this.visiblilidadPanelInformeLineas = false;
			
	        graficoBarras = inicializarGraficoBarras(nodos);
	        graficoBarras.setTitle(titulo);
	        graficoBarras.setAnimate(true);
	        //graficoBarras.setLegendPosition("ne");
	        yAxis = graficoBarras.getAxis(AxisType.Y);
	        
	        yAxis.setTickCount(10);
	    	yAxis.setTickFormat("%d %#d");
	        
	        yAxis.setMin(0);
	        yAxis.setMax(maximoEjeY(nodos));
	        
	        Axis xAxis2 = graficoBarras.getAxis(AxisType.X);
	        xAxis2.setTickAngle(20);
	        
			break;
		case 2: // Grarico de Lineas
			
			this.visiblilidadPanelInformeBarras = false;
			this.visiblilidadPanelInformeLineas = true;
			
			graficoLineas = inicializarGraficoLineas(nodos);
			graficoLineas.setTitle(titulo);
			graficoLineas.setAnimate(true);
			//graficoLineas.setLegendPosition("ne");
			yAxis = graficoLineas.getAxis(AxisType.Y);
			
			yAxis.setTickCount(10);
			yAxis.setTickFormat("%d %#d");
			
	        yAxis.setMin(0);
	        yAxis.setMax(maximoEjeY(nodos));
	        
	        Axis xAxis = graficoLineas.getAxis(AxisType.X);
	        xAxis.setMin(0);
	        xAxis.setTickFormat("%d %#d");
	        
	        xAxis.setMax(nodos.size() + 1);
	        
			break;
		
		}
	}
	
	private LineChartModel inicializarGraficoLineas(List<NodoInformes> nodos) {

		LineChartModel model1 = new LineChartModel();
		 
        ChartSeries ganancias = new ChartSeries();
        
        ganancias.setLabel("Ganancias");
        int i = 1;
        for(NodoInformes nodo : nodos) {
        	
        	ganancias.set(i, Double.parseDouble(nodo.getEjeY()));
        	i++;
        }
        
        model1.addSeries(ganancias);
         
        return model1;
	}



	private BarChartModel inicializarGraficoBarras(List<NodoInformes> nodos) {

		BarChartModel model2 = new BarChartModel();
		 
        ChartSeries ganancias = new ChartSeries();
        
        ganancias.setLabel("Ganancias");
    
        for(NodoInformes nodo : nodos) {
        	
        	ganancias.set(nodo.getEjeX(), Double.parseDouble(nodo.getEjeY()));
        }
        
        model2.addSeries(ganancias);
         
        return model2;
	}



	public String generarInformeGananciaTotalVentas() {
		
		List<NodoInformes> listaNodosInformes = ServiceLocator.getInformesService()
												.gananciaTotalVentas((intervaloSeleccionado != "") ? Integer.parseInt(intervaloSeleccionado) : -1, 
																	 (productoSeleccionado != null) ? productoSeleccionado.getCodigo() : "", 
																	 (clienteSeleccionado != null) ? clienteSeleccionado.getCodigo() : "", 
																	 (tipoRubroSeleccionado != null) ? tipoRubroSeleccionado.getRubro() : "", 
																	 fechaDesde, fechaHasta);
		
		this.setearGrafico(listaNodosInformes, Integer.parseInt(tipoGraficoSeleccionado), "Gananacia de Ventas");

		return null;
	}
	
	public String generarInformeCantidadVentas() {
		
		List<NodoInformes> listaNodosInformes = ServiceLocator.getInformesService()
												.cantidadVentas((intervaloSeleccionado != "") ? Integer.parseInt(intervaloSeleccionado) : -1, 
																	 (productoSeleccionado != null) ? productoSeleccionado.getCodigo() : "", 
																	 (clienteSeleccionado != null) ? clienteSeleccionado.getCodigo() : "", 
																	 (tipoRubroSeleccionado != null) ? tipoRubroSeleccionado.getRubro() : "", 
																	 fechaDesde, fechaHasta);
		
		this.setearGrafico(listaNodosInformes, Integer.parseInt(tipoGraficoSeleccionado), "Cantidad de Ventas");
		
		return null;
	}
	
	public String generarInformeImporteVentas() {
		
		List<NodoInformes> listaNodosInformes = ServiceLocator.getInformesService()
												.importeVentas((intervaloSeleccionado != "") ? Integer.parseInt(intervaloSeleccionado) : -1, 
																	 (productoSeleccionado != null) ? productoSeleccionado.getCodigo() : "", 
																	 (clienteSeleccionado != null) ? clienteSeleccionado.getCodigo() : "", 
																	 (tipoRubroSeleccionado != null) ? tipoRubroSeleccionado.getRubro() : "", 
																	 fechaDesde, fechaHasta);
		
		this.setearGrafico(listaNodosInformes, Integer.parseInt(tipoGraficoSeleccionado), "Importe de Ventas");
		
		return null;
	}
	
	public String generarInformeCantidadCompras() {
		
		List<NodoInformes> listaNodosInformes = ServiceLocator.getInformesService()
												.cantidadCompras((intervaloSeleccionado != "") ? Integer.parseInt(intervaloSeleccionado) : -1, 
																	 (productoSeleccionado != null) ? productoSeleccionado.getCodigo() : "", 
																	 (proveedorSeleccionado != null) ? proveedorSeleccionado.getCodigo() : "", 
																	 fechaDesde, fechaHasta);
		
		this.setearGrafico(listaNodosInformes, Integer.parseInt(tipoGraficoSeleccionado), "Cantidad de Compras");
		
		return null;
	}

	public String generarInformeImporteCompras() {
		
		List<NodoInformes> listaNodosInformes = ServiceLocator.getInformesService()
												.importeCompras((intervaloSeleccionado != "") ? Integer.parseInt(intervaloSeleccionado) : -1, 
																	 (productoSeleccionado != null) ? productoSeleccionado.getCodigo() : "", 
																	 (proveedorSeleccionado != null) ? proveedorSeleccionado.getCodigo() : "", 
																	 fechaDesde, fechaHasta);
		
		this.setearGrafico(listaNodosInformes, Integer.parseInt(tipoGraficoSeleccionado), "Importe de Compras");
		
		return null;
	}
	
	private int maximoEjeY(List<NodoInformes> nodos) {
		
		Double max = new Double(0);
		int suma = 10;
		
		for(NodoInformes n : nodos) {
			
			if(Double.parseDouble(n.getEjeY()) > max)
				max = Double.parseDouble(n.getEjeY());
		}
		
		if(max > 100)
			suma = 100;
		if(max > 1000)
			suma = 500;
		
		return ((int)Math.floor(max) + suma);
	}
	
}
